#if !defined(__APP_DEVICE_H__)
#define __APP_DEVICE_H__

#include <pthread.h>
#include "app_message.h"
#include "app_buffer.h"

typedef struct VTableStruct VTable;

typedef enum DeviceTypeEnum
{
    GENERAL = 0x01,
    SERIAL,
    SPI,
    CAN
} DeviceType;

typedef struct DeviceStruct
{
    // 设备函数虚表，方便子类修改
    VTable *vptr;
    // 设备名
    char *filename;
    // 设备的文件描述符
    int fd;
    // 设备类型
    DeviceType device_type;
    // 设备连接类型
    ConnectionType connection_type;
    // 读缓存
    Buffer *read_buffer;
    // 写缓存
    Buffer *write_buffer;
    // 后台线程ID
    pthread_t background_t;
    // 上次写入的时间戳（自1970.01.01，00:00:00到今天的ms数）
    long last_write_ts;
    long write_interval;
} Device;

struct VTableStruct
{
    // 设备同步后台线程
    void *(*background_thread)(void *);
    // 接收Task
    void (*recv_task)(void *);
    // 发送回调
    void (*send_task)(void *);
    // 接收后处理函数
    void (*post_recv)(Device *, void *, int *);
    // 发送前处理函数
    void (*pre_send)(Device *, void *, int *);
    // 接收回调函数
    int (*recv_callback)(Device *, void *, int);
};

/**
 * @brief 初始化设备
 *
 * @param device 设备
 * @param filename 要初始化的设备文件名
 * @return int 0成功 -1失败
 */
int app_device_init(Device *device, char *filename);

/**
 * @brief 启动设备的后台线程
 *
 * @param device
 * @return int
 */
int app_device_start(Device *device);

/**
 * @brief 向设备中写数据
 *
 * @param device 要写入的设备
 * @param ptr 数据指针
 * @param len 数据长度
 * @return int 0 成功 -1 失败
 */
int app_device_write(Device *device, void *ptr, int len);

/**
 * @brief 向设备注册处理数据的回调函数
 *
 * @param device
 * @param recv_callback
 * @return int
 */
void app_device_registerRecvCallback(Device *device, int (*recv_callback)(Device *, void *, int));

/**
 * @brief 关闭设备的后台线程
 *
 * @param device
 * @return int
 */
int app_device_stop(Device *device);

/**
 * @brief 关闭设备
 *
 * @param device 设备
 */
void app_device_close(Device *device);

#endif // __APP_DEVICE_H__
